package com.zzyl.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.crypto.digest.BCrypt;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.google.common.collect.Sets;
import com.zzyl.base.PageResponse;
import com.zzyl.constant.SuperConstant;
import com.zzyl.dto.UserDto;
import com.zzyl.entity.User;
import com.zzyl.entity.UserRole;
import com.zzyl.mapper.UserMapper;
import com.zzyl.mapper.UserRoleMapper;
import com.zzyl.service.RoleService;
import com.zzyl.service.UserService;
import com.zzyl.utils.EmptyUtil;
import com.zzyl.utils.NoProcessing;
import com.zzyl.vo.RoleVo;
import com.zzyl.vo.UserVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private UserMapper userMapper;

    @Autowired
    RoleService roleService;

    @Autowired
    private UserRoleMapper userRoleMapper;

    @Transactional(rollbackFor = Exception.class)
    @Override
    public PageResponse<UserVo> findUserPage(UserDto userDto, int pageNum, int pageSize) {
        System.out.println("分页查询事务开始>>");

        if (!EmptyUtil.isNullOrEmpty(userDto.getDeptNo())) {
            userDto.setDeptNo(NoProcessing.processString(userDto.getDeptNo()));
        }
        System.out.println("findUserPage_userDto=>" + userDto);
        // 执行分页查询并将Entity转换为VO
        PageHelper.startPage(pageNum, pageSize);
        Page<List<User>> page = userMapper.selectPage(userDto);
        PageResponse<UserVo> pageResponse = PageResponse.of(page, UserVo.class);
        System.out.println("findUserPage_pageResponse:" + pageResponse);

        if (!EmptyUtil.isNullOrEmpty(pageResponse.getRecords())) {
            // 提取当前页所有用户的ID列表
            List<Long> userIds = pageResponse
                    .getRecords()
                    .stream()
                    .map(UserVo::getId)
                    .collect(Collectors.toList());
            System.out.println("findUserPage_userIds:" + userIds);
            // 收集所有用户ID，批量查询这些用户的角色信息 一次性查询所有这些用户的角色信息（避免N+1查询问题）
            // 批量查询1：用户角色信息
            List<RoleVo> roleVoList = roleService.findRoleVoListInUserId(userIds);
            System.out.println("findUserPage_   roleVoList:" + roleVoList);

            // 批量查询2：提取部门编号和岗位编号
            Set<String> deptNos = pageResponse.getRecords().stream()
                    .map(UserVo::getDeptNo)
                    .filter(Objects::nonNull)
                    .collect(Collectors.toSet());

            Set<String> postNos = pageResponse.getRecords().stream()
                    .map(UserVo::getPostNo)
                    .filter(Objects::nonNull)
                    .collect(Collectors.toSet());

            // 批量查询部门和岗位信息
            List<Map<String, Object>> deptList = userMapper.findDeptNamesByNos(deptNos);
            List<Map<String, Object>> postList = userMapper.findPostNamesByNos(postNos);

            // 转换为期望的Map结构：{deptNo: deptName}
            Map<String, String> deptNameMap = deptList.stream()
                    .collect(Collectors.toMap(
                            map -> map.get("deptNo").toString(),      // key: 部门编号
                            map -> map.get("deptName").toString(),    // value: 部门名称
                            (existing, replacement) -> existing       // 重复key处理策略
                    ));

            Map<String, String> postNameMap = postList.stream()
                    .collect(Collectors.toMap(
                            map -> map.get("postNo").toString(),      // key: 岗位编号
                            map -> map.get("postName").toString(),    // value: 岗位名称
                            (existing, replacement) -> existing       // 重复key处理策略
                    ));

            // 调试输出
            System.out.println("部门列表: " + deptList);
            System.out.println("部门Map: " + deptNameMap);
            System.out.println("岗位列表: " + postList);
            System.out.println("岗位Map: " + postNameMap);

            // 装配数据
            pageResponse.getRecords().forEach(userVo -> {
                // 为每个用户初始化角色集合
                Set<String> roleVoIds = Sets.newHashSet();
                Set<String> roleVoLabels = Sets.newHashSet();
                // 遍历所有角色，找到属于当前用户的角色
                roleVoList.forEach(roleVo -> {
                    if (String.valueOf(userVo.getId()).equals(roleVo.getUserId())) {
                        roleVoIds.add(String.valueOf(roleVo.getId()));
                        roleVoLabels.add(roleVo.getRoleName());

                    }
                });
                // 设置到用户VO中
                userVo.setRoleLabels(roleVoLabels);
                userVo.setRoleVoIds(roleVoIds);

                // 装配部门信息
                if (!EmptyUtil.isNullOrEmpty(userVo.getDeptNo())) {
                    userVo.setDeptName(deptNameMap.get(userVo.getDeptNo()));
                }

                // 装配岗位信息
                if (!EmptyUtil.isNullOrEmpty(userVo.getPostNo())) {
                    userVo.setPostName(postNameMap.get(userVo.getPostNo()));
                }

            });
        }
        System.out.println("<<分页查询事务结束");
        return pageResponse;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public UserVo createUser(UserDto userDto) {
        User user = BeanUtil.toBean(userDto, User.class);
        user.setUsername(user.getEmail());
        user.setNickName(user.getRealName());
        String password = BCrypt.hashpw(SuperConstant.DEFAULT_PASSWORD, BCrypt.gensalt());
        user.setPassword(password);
        int flag = userMapper.insert(user);
        if (flag == 0) {
            throw new RuntimeException("保存用户信息出错");
        }

        //保存用户角色中间表
        List<UserRole> userRoles = new ArrayList<>();
        userDto.getRoleVoIds().forEach(roleId -> {
            userRoles.add(UserRole.builder()
                    .userId(user.getId())
                    .roleId(Long.valueOf(roleId))
                    .dataState(SuperConstant.DATA_STATE_0)
                    .build());
        });

        flag = userRoleMapper.batchInsert(userRoles);
        if (flag == 0) {
            throw new RuntimeException("保存用户角色中间表出错");
        }

        return BeanUtil.toBean(user, UserVo.class);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public int updateUser(UserDto userDto) {
        System.out.println("修改事务开始>>");
        System.out.println("updateUser_userDto=>" + userDto);

        // 1. 更新用户基本信息
        User user = BeanUtil.toBean(userDto, User.class);
        System.out.println("updateUser_user=>" + user);
        int flag = userMapper.updateByPrimaryKeySelective(user);

        // 2. 更新用户角色关系（如果传了roleVoIds）
        if (userDto.getRoleVoIds() != null && !userDto.getRoleVoIds().isEmpty()) {
            updateUserRoles(user.getId(), userDto.getRoleVoIds());
        }

        System.out.println("<<修改事务结束");
        return flag;
    }

    @Override
    public UserVo getCurrentUser() {
        // 1. 获取当前登录用户ID
        Long userId = Long.valueOf("1671403256519078138");
        System.out.println("getCurrentUser_userId=>" + userId);
        if (userId == null) {
            throw new RuntimeException("用户未登录");
        }
        // 2. 查询用户基本信息
        User user = userMapper.selectByPrimaryKey(userId);
        if (user == null) {
            throw new RuntimeException("用户不存在");
        }
        System.out.println("getCurrentUser_user=>" + user);
        // 3. 转换为VO
        UserVo userVo = BeanUtil.toBean(user, UserVo.class);
        System.out.println("getCurrentUser_userVo=>" + userVo);
        // 4. 查询并设置角色信息
        List<RoleVo> roleList = roleService.findRoleVoListInUserId(Collections.singletonList(userId));
        System.out.println("getCurrentUser_roleListInUserId=>" + roleList);

        // 使用Set集合
        Set<String> roleLabels = roleList.stream()
                .map(RoleVo::getRoleName)
                .collect(Collectors.toSet());
        System.out.println("getCurrentUser_roleLabels=>" + roleLabels);

        Set<String> roleVoIds = roleList.stream()
                .map(role -> String.valueOf(role.getId()))
                .collect(Collectors.toSet());
        System.out.println("getCurrentUser_roleVoIds=>" + roleVoIds);

        // 设置到userVo中
        userVo.setRoleLabels(roleLabels);
        userVo.setRoleVoIds(roleVoIds);
        userVo.setRoleList(roleList);

        // 6. 设置其他Set类型的集合字段（确保不为null）
        if (userVo.getResourceRequestPaths() == null) {
            userVo.setResourceRequestPaths(Sets.newHashSet());
        }

        if (userVo.getCheckedIds() == null) {
            userVo.setCheckedIds(Sets.newHashSet().toArray(new String[0]));
        }

        // 5. 设置部门和岗位名称
        if (!EmptyUtil.isNullOrEmpty(user.getDeptNo())) {
            List<Map<String, Object>> deptName = userMapper.findDeptNamesByNos(Collections.singleton(user.getDeptNo()));
            userVo.setDeptName((String) deptName.get(0).get("deptName"));
        }

        if (!EmptyUtil.isNullOrEmpty(user.getPostNo())) {
            List<Map<String, Object>> postName = userMapper.findPostNamesByNos(Collections.singleton(user.getPostNo()));
            userVo.setPostName((String) postName.get(0).get("postName"));
        }

        return userVo;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Integer updateUserStatus(Long id, String status) {
        System.out.println("updateUser_status=>" + status);
        // 修改 sys_user
        Integer result1 = userMapper.updateStatusById(id, status);
        if (result1 == 0) {
            throw new RuntimeException("更新sys_user表失败");
        }
        // 修改 sys_user_role
        Integer result2 = userRoleMapper.updateStatusById(id, status);
        if (result2 == 0) {
            throw new RuntimeException("更新sys_user_role表失败");
        }
        return Math.min(result1, result2);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Integer deleteUser(Long userId) {
        System.out.println("deleteUser_userId=>" + userId);
        // 先删除 sys_user_role
        Integer result1 = userMapper.deleteById(userId);
        if (result1 == 0) {
            throw new RuntimeException("删除sys_user_role表失败");
        }
        // 后删除 sys_user
        int result2 = userRoleMapper.deleteByUserId(userId);
        if (result2 == 0) {
            throw new RuntimeException("删除sys_user表失败");
        }
        return Math.min(result1, result2);
    }

    @Override
    public Integer resetPassword(Long userId) {
        System.out.println("resetPassword_userId=>" + userId);
        User user = userMapper.selectByPrimaryKey(userId);
        if (user == null) {
            throw new RuntimeException("该用户不存在");
        }
        String password = BCrypt.hashpw(SuperConstant.DEFAULT_PASSWORD, BCrypt.gensalt());
        Integer result = userMapper.resetPwd(userId, password);
        if (result == 0) {
            throw new RuntimeException("重置失败");
        }
        return result;
    }

    @Override
    public List<UserVo> getUserList(UserDto userDto) {
        // 直接查询列表，不分页
        List<User> userList = userMapper.selectList(userDto);

        return userList.stream()
                .map(user -> {
                    return BeanUtil.toBean(user, UserVo.class);
                })
                .collect(Collectors.toList());
    }
    /**
     * 更新用户角色关系
     */
    private void updateUserRoles(Long userId, Set<String> roleVoIds) {
        // 1. 先删除用户的所有角色关系
        userRoleMapper.deleteByUserId(userId);

        // 2. 批量插入新的角色关系
        if (roleVoIds != null && !roleVoIds.isEmpty()) {
            List<UserRole> userRoles = roleVoIds.stream()
                    .map(roleId -> {
                        UserRole userRole = new UserRole();
                        userRole.setUserId(userId);
                        userRole.setDataState(SuperConstant.DATA_STATE_0);
                        userRole.setRoleId(Long.valueOf(roleId));
                        return userRole;
                    })
                    .collect(Collectors.toList());

            userRoleMapper.batchInsert(userRoles);
        }
    }
}
